package cloudspace.ui.applet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;


public class AppletReflectionProvider implements ReflectionProvider
{

    public Object newInstance( Class type )
    {
        try
        {
            return type.newInstance();
        }
        catch ( InstantiationException e )
        {
            e.printStackTrace();
        }
        catch ( IllegalAccessException e )
        {
            // THIS WILL NEVER HAPPEN :-). I modify their code.
            e.printStackTrace();
        }
        return null;
    }


    public void visitSerializableFields( Object object, Visitor visitor )
    {
        visitFieldHelper( object.getClass(), object, visitor );
    }


    private void visitFieldHelper( Class type, Object object, Visitor visitor )
    {
        Field[] definedFields = type.getDeclaredFields();
        for ( Field declared : definedFields )
        {
            // Use a specialized injected method to access all of the members.
            // In your base killin your dudes.
            Object value = null;
            try
            {
                Method meth = object.getClass().getMethod( "_get_value_",
                    new Class<?>[] { String.class } );
                // System.out.println("looking up "+declared.getName());
                value = meth.invoke( object, declared.getName() );
            }
            catch ( Exception e )
            {
                // JUST IGNORE AND RETURN NULL
                // e.printStackTrace();
            }
            // System.out.println("Visiting "+declared.getName()+" with value "+value);
            visitor.visit( declared.getName(),
                declared.getType(),
                object.getClass(),
                value );
        }
        Class<?> superClass = type.getSuperclass();
        if ( superClass != null && !superClass.equals( Object.class ) )
        {
            visitFieldHelper( superClass, object, visitor );
        }
    }


    public void writeField(
        Object object,
        String fieldName,
        Object value,
        Class definedIn )
    {
        try
        {
            // System.out.println("Replacing "+fieldName+" with "+value);
            Method writeMeth = definedIn.getMethod( "_write_field_",
                new Class<?>[] { String.class, Object.class } );
            try
            {
                writeMeth.invoke( object, fieldName, value );
            }
            catch ( Exception e )
            {
                // Ignore and leave null. This means an exception has occured
                // when reloading the field.
            }
        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }

    }


    public Class getFieldType( Object object, String fieldName, Class definedIn )
    {
        try
        {
            return definedIn.getDeclaredField( fieldName ).getType();
        }
        catch ( SecurityException e )
        {
            e.printStackTrace();
        }
        catch ( NoSuchFieldException e )
        {
            e.printStackTrace();
        }
        return null;
    }


    public boolean fieldDefinedInClass( String fieldName, Class type )
    {

        try
        {
            return type.getDeclaredField( fieldName ) != null;
        }
        catch ( SecurityException e )
        {
            e.printStackTrace();
        }
        catch ( NoSuchFieldException e )
        {
            e.printStackTrace();
        }
        return false;
    }


    public Field getField( Class definedIn, String fieldName )
    {
        try
        {
            return definedIn.getDeclaredField( fieldName );
        }
        catch ( SecurityException e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch ( NoSuchFieldException e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}
